home *** CD-ROM | disk | FTP | other *** search
- #!/usr/bin/perl -w
- #
- # $Id: GKismetApplication.pm,v 1.70 2003/08/01 01:37:00 solovam Exp $
- #
- # This file is a part of gkismet
- #
- # This program is free software; you can redistribute it and/or
- # modify it under the terms of the GNU General Public License
- # as published by the Free Software Foundation; either version 2
- # of the License, or (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program; if not, write to the Free Software
- # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- #
-
- #
- # GKismetApplication class:
- #
- package GKismetApplication;
-
- use Gnome;
- use PacketBox;
- use NetworkTree;
- use StatusBar;
- use Connection;
- use ConnectionDialog;
- use PrefsDialog;
- use AboutDialog;
- use Preferences;
- use PacketWindow;
- use StringWindow;
- use PowerBox;
- use GpsBox;
- use Locator;
- use RateGraph;
- use BoomBox;
- use Misc;
- use strict;
-
- #
- # Constructor
- #
- sub new
- {
- my $type = shift;
- my $self = {};
- bless $self, $type;
-
- # Paths
- my $prefix = shift;
- $self->{'path'}{'xpm'} = $prefix . '/share/gkismet/xpm';
- $self->{'path'}{'sound'} = $prefix . '/share/gkismet/sound';
- $self->{'path'}{'etc'} = '/etc/gkismet';
-
- # Gnome init
- init Gnome 'gkismet';
-
- # Create app
- my $application = new Gnome::App("gkismet", "gkismet");
- $self->{'application'} = $application;
- $application->set_default_size(Gtk::Gdk->screen_width() * 0.6, Gtk::Gdk->screen_height() * 0.8);
- $application->signal_connect("delete_event", sub {Gtk->exit(0)});
-
- # Preferences
- my $preferences = new Preferences($self);
- $self->{'preferences'} = $preferences;
-
- # Status line
- my $statusBar = new StatusBar($self);
- $self->{'persistentObservers'}{'statusBar'} = $statusBar;
-
- # My info box
- my $packetBox = new PacketBox($self);
- $self->{'persistentObservers'}{'packetBox'} = $packetBox;
-
- # My power box
- my $powerBox = new PowerBox($self);
- $self->{'persistentObservers'}{'powerBox'} = $powerBox;
-
- # My GPS box
- my $gpsBox = new GpsBox($self);
- $self->{'persistentObservers'}{'gpsBox'} = $gpsBox;
-
- # Ntree
- my $networkTree = new NetworkTree($self);
- $self->{'persistentObservers'}{'networkTree'} = $networkTree;
- $networkTree->addObserver($self);
-
- my $boomBox = new BoomBox($self);
- $self->{'persistentObservers'}{'boomBox'} = $boomBox;
-
- # Build menu info
- my @menuInfo =
- (
- {
- type => 'subtree', label => '_File', subtree =>
- [
- {type => 'item', label => '_Connect', pixmap_type => 'stock', pixmap_info => 'Menu_Open',
- callback => sub {$self->connect()}},
- {type => 'item', label => '_Disconnect', pixmap_type => 'stock', pixmap_info => 'Menu_Close',
- callback => sub {$self->disconnect()}},
- {type => 'separator'},
- {type => 'item', label => '_Quit', pixmap_type => 'stock', pixmap_info => 'Menu_Quit',
- callback => sub {Gtk->exit(0)}}
- ]
- },
- {
- type => 'subtree', label => '_View', subtree =>
- [
- {type => 'item', label => '_Expand', pixmap_type => 'stock', pixmap_info => 'Menu_Book Open',
- callback => sub {$self->{'persistentObservers'}{'networkTree'}->expand()}},
- {type => 'item', label => '_Collapse', pixmap_type => 'stock', pixmap_info => 'Menu_Book Red',
- callback => sub {$self->{'persistentObservers'}{'networkTree'}->collapse()}},
- {type => 'item', label => '_Packet Dump', pixmap_type => 'stock', pixmap_info => 'Menu_Timer',
- callback => sub {$self->bssObserverOpenSelected('PacketWindow')}},
- {type => 'item', label => '_String Dump', pixmap_type => 'stock', pixmap_info => 'Menu_Timer',
- callback => sub {$self->bssObserverOpenSelected('StringWindow')}},
- {type => 'item', label => '_Locate', pixmap_type => 'stock', pixmap_info => 'Menu_Search',
- callback => sub {$self->bssObserverOpenSelected('Locator')}},
- {type => 'item', label => 'Packet _rate', pixmap_type => 'stock', pixmap_info => 'Menu_Timer',
- callback => sub {$self->transObserverOpen('RateGraph')}},
- {type => 'subtree', label => 'Sort', subtree =>
- [
- {type => 'item', label => 'Ascending',
- callback => sub {$self->{'persistentObservers'}{'networkTree'}->setSortOrder('ascending')}},
- {type => 'item', label => 'Descending',
- callback => sub {$self->{'persistentObservers'}{'networkTree'}->setSortOrder('descending')}},
- ]
- },
- {type => 'subtree', label => 'Sort Networks', subtree =>
- [
- {type => 'item', label => 'By channel',
- callback => sub {$self->{'persistentObservers'}{'networkTree'}->setNetworksSortBy('channel')}},
- {type => 'item', label => 'By first seen',
- callback => sub {$self->{'persistentObservers'}{'networkTree'}->setNetworksSortBy('firsttime')}},
- {type => 'item', label => 'By last seen',
- callback => sub {$self->{'persistentObservers'}{'networkTree'}->setNetworksSortBy('lasttime')}},
- {type => 'item', label => 'By BSSID',
- callback => sub {$self->{'persistentObservers'}{'networkTree'}->setNetworksSortBy('bssid')}},
- {type => 'item', label => 'By SSID',
- callback => sub {$self->{'persistentObservers'}{'networkTree'}->setNetworksSortBy('ssid')}},
- {type => 'item', label => 'By data packet count',
- callback => sub {$self->{'persistentObservers'}{'networkTree'}->setNetworksSortBy('datapackets')}},
- {type => 'item', label => 'By signal power',
- callback => sub {$self->{'persistentObservers'}{'networkTree'}->setNetworksSortBy('signal')}},
- {type => 'item', label => 'By WEP',
- callback => sub {$self->{'persistentObservers'}{'networkTree'}->setNetworksSortBy('wep')}},
- ]
- },
- {type => 'subtree', label => 'Sort Clients', subtree =>
- [
- {type => 'item', label => 'By first seen',
- callback => sub {$self->{'persistentObservers'}{'networkTree'}->setClientsSortBy('firsttime')}},
- {type => 'item', label => 'By last seen',
- callback => sub {$self->{'persistentObservers'}{'networkTree'}->setClientsSortBy('lasttime')}},
- {type => 'item', label => 'By MAC',
- callback => sub {$self->{'persistentObservers'}{'networkTree'}->setClientsSortBy('mac')}},
- {type => 'item', label => 'By data packet count',
- callback => sub {$self->{'persistentObservers'}{'networkTree'}->setClientsSortBy('datapackets')}},
- {type => 'item', label => 'By signal power',
- callback => sub {$self->{'persistentObservers'}{'networkTree'}->setClientsSortBy('signal')}},
- {type => 'item', label => 'By WEP',
- callback => sub {$self->{'persistentObservers'}{'networkTree'}->setClientsSortBy('wep')}},
- ]
- }
- ]
- },
- {
- type => 'subtree', label => '_Settings', subtree =>
- [
- {type => 'item', label => '_Preferences', pixmap_type => 'stock', pixmap_info => 'Menu_Preferences',
- callback => sub{$self->dialogOpen('PrefsDialog')}}
- ]
- },
- {
- type => 'subtree', label => '_Help', subtree =>
- [
- {type => 'item', label => '_About', pixmap_type => 'stock', pixmap_info => 'Menu_About',
- callback => sub{$self->dialogOpen('AboutDialog')}}
- ]
- }
- );
-
- # Build toolbar info
- my @toolbarInfo = (
- {type => 'item', label => 'Connect', pixmap_type => 'stock', pixmap_info => 'Open', 'hint' => 'Connect to Kismet server',
- callback => sub {$self->connect()}},
- {type => 'item', label => 'Disconnect', pixmap_type => 'stock', pixmap_info => 'Close', 'hint' => 'Disconnect from Kismet server',
- callback => sub {$self->disconnect()}},
- {type => 'item', label => 'Expand', pixmap_type => 'stock', pixmap_info => 'Book Open', 'hint' => 'Expand network node',
- callback => sub {$self->{'persistentObservers'}{'networkTree'}->expand()}},
- {type => 'item', label => 'Collapse', pixmap_type => 'stock', pixmap_info => 'Book Red', 'hint' => 'Collapse network node',
- callback => sub {$self->{'persistentObservers'}{'networkTree'}->collapse()}},
- {type => 'item', label => 'Packet Dump', pixmap_type => 'stock', pixmap_info => 'Timer', 'hint' => 'Open packet dump window',
- callback => sub {$self->bssObserverOpenSelected('PacketWindow')}},
- {type => 'item', label => 'String Dump', pixmap_type => 'stock', pixmap_info => 'Timer', 'hint' => 'Open string dump window',
- callback => sub {$self->bssObserverOpenSelected('StringWindow')}},
- {type => 'item', label => 'Locate', pixmap_type => 'stock', pixmap_info => 'Search', 'hint' => 'Open locator window',
- callback => sub {$self->bssObserverOpenSelected('Locator')}},
- {type => 'item', label => 'Packet rate', pixmap_type => 'stock', pixmap_info => 'Timer', 'hint' => 'Open packet rate window',
- callback => sub {$self->transObserverOpen('RateGraph')}},
- );
-
- # Pack widgets
- my $scrolledWindow = new Gtk::ScrolledWindow(undef, undef);
- $scrolledWindow->set_policy('automatic', 'automatic');
- my $vbox = new Gtk::VBox($false, 0);
- $vbox->pack_start($packetBox->getWidget(), $false, $false, 10);
- $vbox->pack_start($gpsBox->getWidget(), $false, $false, 10);
- $vbox->pack_start($powerBox->getWidget(), $true, $true, 10);
- my $hbox = new Gtk::HBox($false, 0);
- $hbox->pack_start($scrolledWindow, $true, $true, 0);
- $hbox->pack_end($vbox, $false, $false, 10);
- $scrolledWindow->add($networkTree->getWidget());
-
- # Assemble main window
- $application->create_menus(@menuInfo);
- $application->create_toolbar(@toolbarInfo);
- $application->set_statusbar($statusBar->getWidget());
- $application->set_contents($hbox);
- $application->show_all();
-
- # Items become active when a network is selected
- $self->{'selectedActItems'}{'expandMenuItem'} = $self->findWidgetInMenu(\@menuInfo, '_Expand');
- $self->{'selectedActItems'}{'collapseMenuItem'} = $self->findWidgetInMenu(\@menuInfo, '_Collapse');
- $self->{'selectedActItems'}{'packetDumpMenuItem'} = $self->findWidgetInMenu(\@menuInfo, '_Packet Dump');
- $self->{'selectedActItems'}{'stringDumpMenuItem'} = $self->findWidgetInMenu(\@menuInfo, '_String Dump');
- $self->{'selectedActItems'}{'locatorMenuItem'} = $self->findWidgetInMenu(\@menuInfo, '_Locate');
- $self->{'selectedActItems'}{'expandToolbarItem'} = $self->findWidgetInMenu(\@toolbarInfo, 'Expand');
- $self->{'selectedActItems'}{'collapseToolbarItem'} = $self->findWidgetInMenu(\@toolbarInfo, 'Collapse');
- $self->{'selectedActItems'}{'packetDumpToolbarItem'} = $self->findWidgetInMenu(\@toolbarInfo, 'Packet Dump');
- $self->{'selectedActItems'}{'stringDumpToolbarItem'} = $self->findWidgetInMenu(\@toolbarInfo, 'String Dump');
- $self->{'selectedActItems'}{'locatorToolbarItem'} = $self->findWidgetInMenu(\@toolbarInfo, 'Locate');
- for my $item (values %{$self->{'selectedActItems'}})
- {
- $item->set_sensitive($false);
- }
-
- # Items become active when a connection is established
- $self->{'connectedActItems'}{'rateMenuItem'} = $self->findWidgetInMenu(\@menuInfo, 'Packet _rate');
- $self->{'connectedActItems'}{'rateToolbarItem'} = $self->findWidgetInMenu(\@toolbarInfo, 'Packet rate');
- for my $item (values %{$self->{'connectedActItems'}})
- {
- $item->set_sensitive($false);
- }
-
- return $self;
- }
-
- #
- # Find widget with specific label
- #
- sub findWidgetInMenu
- {
- my $self = shift;
- my $menu = shift;
- my $label = shift;
-
- for my $item (@{$menu})
- {
- my $widget = $self->findWidget($item, $label);
- if(defined $widget)
- {
- return $widget;
- }
- }
- return undef;
- }
-
- #
- # Find widget for a menu/toolbar item. Plucked from Gnome-Perl samples
- #
- sub findWidget
- {
- my $self = shift;
- my $item = shift;
- my $label = shift;
- my $subtree;
-
- # Array
- if(ref($item) eq 'ARRAY')
- {
- # If found, return
- if($item->[0] eq 'item' && $item->[1] eq $label)
- {
- return $item->[-1];
- }
-
- # Is there a subtree?
- if($item->[0] eq 'subtree')
- {
- $subtree = $item->[3];
- }
- }
- # Hash
- else
- {
- # If found, return
- if($item->{'type'} eq 'item' && $item->{'label'} eq $label)
- {
- return $item->{'widget'};
- }
-
- # Is there a subtree?
- if ($item->{type} eq 'radioitems')
- {
- $subtree = $item->{'moreinfo'};
- }
- if($item->{'type'} eq 'subtree')
- {
- $subtree = $item->{'subtree'};
- }
- }
-
- # If there was a subtree
- if(defined $subtree)
- {
- for (@{$subtree})
- {
- my $widget = $self->findWidget($_, $label);
- if(defined $widget)
- {
- return $widget;
- }
- }
- }
-
- # Not found
- return undef;
- }
-
- #
- # Connect to server
- #
- sub connect
- {
- my $self = shift;
- my $host = shift;
- my $port = shift;
-
- if(defined $self->{'connection'})
- {
- $self->disconnect();
- }
-
- if(!defined $host || !defined $port)
- {
- my $connectionDialog = new ConnectionDialog($self);
- ($host, $port) = $connectionDialog->runAndClose();
- if(!defined $host)
- {
- return(0);
- }
- }
-
- my $connection = new Connection($self, $host, $port);
- if(!defined $connection)
- {
- my $messagebox = new Gnome::MessageBox("Can't connect to kismet server at $host:$port", 'error', 'Button_Ok');
- $messagebox->run_and_close();
- return(0);
- }
- $self->{'connection'} = $connection;
-
- $connection->addObserver($self);
-
- for my $item (values %{$self->{'connectedActItems'}})
- {
- $item->set_sensitive($true);
- }
-
- for my $observer (values %{$self->{'persistentObservers'}})
- {
- $observer->startObserving($connection);
- }
-
- return(1);
- }
-
- #
- # Disconnect
- #
- sub disconnect
- {
- my $self = shift;
-
- if(!defined $self->{'connection'})
- {
- return;
- }
-
- for my $observer (values %{$self->{'persistentObservers'}})
- {
- $observer->stopObserving();
- }
- for my $type (keys %{$self->{'transientObservers'}})
- {
- $self->transObserverClose($type);
- }
- for my $type (keys %{$self->{'bssObservers'}})
- {
- for my $bssid (keys %{$self->{'bssObservers'}{$type}})
- {
- $self->bssObserverClose($type, $bssid);
- }
- }
-
- for my $item (values %{$self->{'connectedActItems'}})
- {
- $item->set_sensitive($false);
- }
-
- $self->{'connection'}->removeObserver($self);
-
- $self->{'connection'}->disconnect();
-
- delete $self->{'connection'};
- }
-
- #
- # Handle server quit
- #
- sub update
- {
- my $self = shift;
- my $object = shift;
- my $data = shift;
-
- if($object->isa('Connection') && defined $self->{'connection'} && $self->{'connection'} eq $object)
- {
- if($data->{'changed'} eq 'disconnected')
- {
- my $messagebox = new Gnome::MessageBox("Lost connection to kismet server at " .
- $self->{'connection'}->host() . ":" . $self->{'connection'}->port(), 'error', 'Button_Ok');
- $messagebox->run_and_close();
-
- $self->disconnect();
- }
- }
- elsif($object->isa('NetworkTree') && $self->{'persistentObservers'}{'networkTree'} eq $object)
- {
- if($data->{'changed'} eq 'selection')
- {
- if($self->{'persistentObservers'}{'networkTree'}->getSelectedNetworks())
- {
- for my $item (values %{$self->{'selectedActItems'}})
- {
- $item->set_sensitive($true);
- }
- }
- else
- {
- for my $item (values %{$self->{'selectedActItems'}})
- {
- $item->set_sensitive($false);
- }
- }
- }
- }
- }
-
- #
- # Run the app
- #
- sub run
- {
- my $self = shift;
-
- my ($progname) = ($0 =~ /([^\/]*)$/);
- my $usage = "$progname <host> [port]\n";
-
- if($#ARGV > 1)
- {
- print $usage;
- exit 1;
- }
-
- my $host = $ARGV[0];
- my $port = $ARGV[1] ? $ARGV[1] : 2501;
-
- $self->connect($host, $port);
-
- main Gtk;
-
- exit(0);
- }
-
- #
- # Get widget
- #
- sub getWidget
- {
- my $self = shift;
- return $self->{'application'};
- }
-
- #
- # Show a dialog
- #
- sub dialogOpen
- {
- my $self = shift;
- my $type = shift;
- $type = lcfirst($type);
- if(!defined $self->{'dialogs'}{$type})
- {
- my $dialog = ucfirst($type)->new($self);
- $self->{'dialogs'}{$type} = $dialog;
- }
- else
- {
- $self->{'dialogs'}{$type}->getWidget()->window()->raise();
- }
- }
-
- #
- # Close dialog
- #
- sub dialogClose
- {
- my $self = shift;
- my $type = shift;
- $type = lcfirst($type);
- delete $self->{'dialogs'}{$type};
- }
-
- #
- # Return number of observers by type
- #
- sub countObservers
- {
- my $self = shift;
- my $type = shift;
- $type = lcfirst($type);
- return scalar keys %{$self->{'bssObservers'}{$type}};
- }
-
- #
- # Open observers for selected networks
- #
- sub bssObserverOpenSelected
- {
- my $self = shift;
- my $type = shift;
- my @selected = $self->{'persistentObservers'}{'networkTree'}->getSelectedNetworks();
- for my $bssid (@selected)
- {
- $self->bssObserverOpen($type, $bssid);
- }
- }
-
- #
- # Open an observer for bssid
- #
- sub bssObserverOpen
- {
- my $self = shift;
- my $type = shift;
- my $bssid = shift;
-
- $type = lcfirst($type);
- if(!defined $self->{'bssObservers'}{$type}{$bssid})
- {
- $self->{'bssObservers'}{$type}{$bssid} = ucfirst($type)->new($self, $self->{'connection'}, $bssid);
- }
- else
- {
- $self->{'bssObservers'}{$type}{$bssid}->getWidget()->window()->raise();
- }
- }
-
- #
- # Close observers for selected networks
- #
- sub bssObserverCloseSelected
- {
- my $self = shift;
- my $type = shift;
- my @selected = $self->{'persistentObservers'}{'networkTree'}->getSelectedNetworks();
- for my $bssid (@selected)
- {
- $self->bssObserverClose($type, $bssid);
- }
- }
-
- #
- # Close an observer for bssid
- #
- sub bssObserverClose
- {
- my $self = shift;
- my $type = shift;
- my $bssid = shift;
- $type = lcfirst($type);
- if(defined $self->{'bssObservers'}{$type}{$bssid})
- {
- $self->{'bssObservers'}{$type}{$bssid}->close();
- delete $self->{'bssObservers'}{$type}{$bssid};
- }
- }
-
- #
- # Open observer
- #
- sub transObserverOpen
- {
- my $self = shift;
- my $type = shift;
-
- if(!defined $self->{'connection'})
- {
- return;
- }
-
- $type = lcfirst($type);
- if(!defined $self->{'transientObservers'}{$type})
- {
- $self->{'transientObservers'}{$type} = ucfirst($type)->new($self, $self->{'connection'});
- }
- else
- {
- $self->{'transientObservers'}{$type}->getWidget()->window()->raise();
- }
- }
-
- #
- # Close observer
- #
- sub transObserverClose
- {
- my $self = shift;
- my $type = shift;
- $type = lcfirst($type);
- if(defined $self->{'transientObservers'}{$type})
- {
- $self->{'transientObservers'}{$type}->close();
- delete $self->{'transientObservers'}{$type};
- }
- }
-
- 1;
-